﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>测量功能</title>
    <!--引入当前页面样式表-->
    <link href="./style.css" rel="stylesheet" type="text/css"/>
    <script include="jquery" src="./static/libs/include-lib-local.js"></script>
    <script src="./static/libs/include-openlayers-local.js"></script>
    <style type="text/css">
        .tooltip {
            position: relative;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 4px;
            color: white;
            padding: 4px 8px;
            opacity: 0.7;
            white-space: nowrap;
        }

        .tooltip-measure {
            opacity: 1;
            font-weight: bold;
        }

        .tooltip-static {
            background-color: #ffcc33;
            color: black;
            border: 1px solid white;
        }

        .tooltip-measure::before, .tooltip-static::before {
            border-top: 6px solid rgba(0, 0, 0, 0.5);
            border-right: 6px solid transparent;
            border-left: 6px solid transparent;
            content: "";
            position: absolute;
            bottom: -6px;
            margin-left: -7px;
            left: 50%;
        }

        .tooltip-static::before {
            border-top-color: #ffcc33;
        }
    </style>
    <script type="text/javascript">

        "use strict";
        //定义地图文档图层和地图
        var mapDocLayer, map;
        var drawLayer;//绘制矢量图层
        var source;//绘制矢量图层的source
        var tooltipCoord;//提示框位置坐标
        var listener;//绘制坐标变化监听
        var helpTooltipElement;//绘制过程中提示框div
        var helpTooltip;//绘制过程中提示框
        var draw;//绘制事件
        var measureTooltipElement;//测量提示框div
        var measureTooltip;//测量提示框
        var sketch;//绘制标志
        var { protocol, ip, port } = window.webclient;

        /** 初始化地图显示*/
        function init() {
            //初始化地图容器
            map = new ol.Map({
                target: "mapCon",
                view: new ol.View({
                    center: [(108.34341 + 116.150939561213) / 2, (29.0125822276524 + 33.2932017737021) / 2],
                    zoom: 6,
                    projection: "EPSG:4326"
                })
            });
            //初始化地图文档图层对象
            mapDocLayer = new Zondy.Map.MapDocTileLayer("MapGIS IGS MapDocLayer", "Hubei4326", {
                ip: `${ip}`,
                port: `${port}`
            });
            //将地图文档图层加载到地图中
            map.addLayer(mapDocLayer);

            //加载测量的绘制矢量层
            source = new ol.source.Vector(); //图层数据源
            drawLayer = new ol.layer.Vector({
                source: source,
                style: new ol.style.Style({ //图层样式
                    fill: new ol.style.Fill({
                        color: 'rgba(51,136,255, 0.2)' //填充颜色
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#3388ff',  //边框颜色
                        width: 4   // 边框宽度
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#3388ff'
                        })
                    })
                })
            });
            map.addLayer(drawLayer);
        }

        //增加绘制交互事件
        function addInteraction() {
            var type = "Polygon";
            draw = new ol.interaction.Draw({
                source: source,
                type: (type),
                style: new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(51,136,255, 0.2)' //填充颜色
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#3388ff',  //边框颜色
                        width: 4   // 边框宽度
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#3388ff'
                        })
                    })
                })
            });
            map.addInteraction(draw);
            createMeasureTooltip();//创建测量提示
            createHelpTooltip();//创建绘制过程中提示
            var flatCoordinates;
            draw.on('drawstart',
                function (evt) {
                    sketch = evt.feature;
                    listener = sketch.getGeometry().on("change", function (evt) {
                        var geom = evt.target;
                        flatCoordinates = geom.flatCoordinates;
                    });
                }, this);
            draw.on('drawend',
                function (evt) {
                    var dots = [];
                    var length = flatCoordinates.length;
                    for (var i = 0; i < length; i += 2) {
                        dots.push(new Zondy.Object.Point2D(flatCoordinates[i],
                            flatCoordinates[i + 1]))
                    }
                    tooltipCoord = getCenterOfGravityPoint(dots);
                    //获取要计算面积的几何对象点集，服务端计算
                    calArea(dots)
                }, this);

            var pointerMoveHandler = function (evt) {
                if (evt.dragging) {
                    return;
                }
                var helpMsg = "Click to start drawing";
                if (sketch) {
                    helpMsg = "Click to continue drawing the line";
                }
                helpTooltipElement.innerHTML = helpMsg;
                helpTooltip.setPosition(evt.coordinate);
                $(helpTooltipElement).removeClass("hidden");
            };

            map.on("pointermove", pointerMoveHandler);
            $(map.getViewport()).on("mouseout", function () {
                $(helpTooltipElement).addClass("hidden");
            });
        }

        /**
         * 获取多边形重心
         * @param dots
         * @returns {{x: number, y: number}}
         */
        function getCenterOfGravityPoint(dots) {
            let area = 0.0;// 多边形面积
            let Gx = 0.0;
            let Gy = 0.0;// 重心的x、y
            for (let i = 1; i <= dots.length; i++) {
                const iLat = dots[i % dots.length].y;
                const iLng = dots[i % dots.length].x;
                const nextLat = dots[i - 1].y;
                const nextLng = dots[i - 1].x;
                const temp = (iLat * nextLng - iLng * nextLat) / 2.0;
                area += temp;
                Gy += temp * (iLat + nextLat) / 3.0;
                Gx += temp * (iLng + nextLng) / 3.0
            }
            return [Gx / area, Gy / area]
        }

        /** 创建绘制过程中提示*/
        function createHelpTooltip() {
            if (helpTooltipElement) {
                helpTooltipElement.parentNode.removeChild(helpTooltipElement);
            }
            helpTooltipElement = document.createElement("div");
            helpTooltipElement.className = "tooltip hidden";
            helpTooltip = new ol.Overlay({
                element: helpTooltipElement,
                offset: [15, 0],
                positioning: "center-left"
            });
            map.addOverlay(helpTooltip);
        }

        /** 创建测量提示*/
        function createMeasureTooltip() {
            if (measureTooltipElement) {
                measureTooltipElement.parentNode.removeChild(measureTooltipElement);
            }
            measureTooltipElement = document.createElement("div");
            measureTooltipElement.className = "tooltip tooltip-measure";
            measureTooltip = new ol.Overlay({
                element: measureTooltipElement,
                offset: [0, 15],
                positioning: "bottom-center"
            });
            map.addOverlay(measureTooltip);
        }

        /** 计算折线长度*/
        function calArea(dots) {
            //初始化长度测量服务
            var calLength = new Zondy.Service.CalArea(dots, {
                //IP地址
                ip: `${ip}`,
                //端口号
                port: `${port}`
            });
            //建议普通用户采用此类直接获取MapGIS GDB已经提供的空间参考系
            var gdbInfo = new Zondy.Object.CGDBInfo({
                //数据库名称
                GDBName: "OpenLayerVecterMap",
                //数据源名称
                ServerName: "MapGISLocal",
                //除MapGISLocal数据源，其它的都设置
                Password: "",
                //除MapGISLocal数据源，其它的都设置
                User: ""
            });
            //用于进行SRSID投影的参数类
            var projBySRSID = new Zondy.Service.CProjectBySRSID(601, gdbInfo);
            //执行长度测量服务，measureCallBack为测量回调函数
            calLength.execute(projBySRSID, measureCallBack);
        }

        /** 测量回调函数
         *  @param {json对象} data 获取结果对象
         */
        function measureCallBack(data) {
            if (data && data.succeed) {
                var area = data.value;
                var output;
                if (area > 10000) {
                    output = (Math.round(area / 1000000 * 100) / 100) + "" + "km<sup>2</sup>";
                } else {
                    output = (Math.round(area * 100) / 100) + "" + "m<sup>2</sup>";
                }
                measureTooltipElement.innerHTML = output;
                measureTooltip.setPosition(tooltipCoord);
                measureTooltipElement.className = 'tooltip tooltip-static';
                measureTooltipElement.id = 'tooltip-static';
                measureTooltip.setOffset([0, -7]);
                sketch = null;
                measureTooltipElement = null;
                createMeasureTooltip();
                ol.Observable.unByKey(listener);
            }
        }

        /** 清除测量结果*/
        function deleteMeasure() {
            source.clear();
            map.getOverlays().clear();
            map.removeInteraction(draw);
        }
    </script>
</head>
<body onload="init()">
<div class="ToolLib">
    <input type="button" class="ButtonLib" value="绘制多边形" onclick='addInteraction()'/>
    <input type="button" class="ButtonLib" value="清除测量结果" onclick='deleteMeasure()'/>
    <div id="introduction">
        <font style=" float: left; text-align: left">说明：该示例是在程序里面给定点坐标进行面积测量</font><br/>
    </div>
</div>
<div id="mapCon" style="position: absolute; width: 100%; height:95%;">
</div>
</body>
</html>
